#include "utils.h"
#include <iostream>
#include <sstream>
#include <algorithm>
#include <cctype>
#include <ctime>
#include <iomanip>

namespace FileScanner {

long long parseFileSize(const std::string& sizeStr) {
    if (sizeStr.empty()) {
        return -1;
    }

    std::string str = sizeStr;

    // 转换为小写
    std::transform(str.begin(), str.end(), str.begin(), ::tolower);

    // 查找数字部分的结束位置
    size_t numEnd = 0;
    while (numEnd < str.length() && (std::isdigit(str[numEnd]) || str[numEnd] == '.')) {
        numEnd++;
    }

    if (numEnd == 0) {
        return -1;
    }

    // 解析数字部分
    double value;
    try {
        value = std::stod(str.substr(0, numEnd));
    } catch (const std::exception&) {
        return -1;
    }

    // 解析单位部分
    std::string unit = str.substr(numEnd);

    // 移除空格
    unit.erase(std::remove_if(unit.begin(), unit.end(), ::isspace), unit.end());

    long long multiplier = 1;

    if (unit.empty() || unit == "b" || unit == "byte" || unit == "bytes") {
        multiplier = 1;
    } else if (unit == "k" || unit == "kb" || unit == "kib") {
        multiplier = 1024;
    } else if (unit == "m" || unit == "mb" || unit == "mib") {
        multiplier = 1024 * 1024;
    } else if (unit == "g" || unit == "gb" || unit == "gib") {
        multiplier = 1024 * 1024 * 1024;
    } else {
        return -1;
    }

    return static_cast<long long>(value * multiplier);
}

std::string formatFileSize(long long bytes) {
    const char* units[] = {"B", "KB", "MB", "GB", "TB"};
    const int numUnits = sizeof(units) / sizeof(units[0]);

    double size = static_cast<double>(bytes);
    int unitIndex = 0;

    while (size >= 1024.0 && unitIndex < numUnits - 1) {
        size /= 1024.0;
        unitIndex++;
    }

    std::ostringstream oss;
    if (unitIndex == 0) {
        oss << static_cast<long long>(size) << " " << units[unitIndex];
    } else {
        oss << std::fixed << std::setprecision(1) << size << " " << units[unitIndex];
    }

    return oss.str();
}

std::string getCurrentTimeString() {
    auto now = std::time(nullptr);
    auto tm = *std::localtime(&now);

    std::ostringstream oss;
    oss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S");
    return oss.str();
}

void logMessage(const std::string& message) {
    std::cout << "[" << getCurrentTimeString() << "] " << message << std::endl;
}

void logError(const std::string& message) {
    std::cerr << "[" << getCurrentTimeString() << "] ERROR: " << message << std::endl;
}

std::string joinPath(const std::string& basePath, const std::string& relativePath) {
    if (basePath.empty()) {
        return relativePath;
    }

    if (relativePath.empty()) {
        return basePath;
    }

    // 检查 basePath 是否以 '/' 结尾，relativePath 是否以 '/' 开头
    bool baseEndsWithSlash = (basePath.back() == '/');
    bool relativeStartsWithSlash = (relativePath.front() == '/');

    if (baseEndsWithSlash && relativeStartsWithSlash) {
        // 两边都有斜线，去掉 relativePath 开头的斜线
        return basePath + relativePath.substr(1);
    } else if (!baseEndsWithSlash && !relativeStartsWithSlash) {
        // 两边都没有斜线，添加一个斜线
        return basePath + "/" + relativePath;
    } else {
        // 一边有斜线，直接连接
        return basePath + relativePath;
    }
}

void showHelp() {
    std::cout << "文件扫描工具，计算文件的MD5值并存储到数据库中\n\n";
    std::cout << "用法: filescanner [选项]\n\n";
    std::cout << "选项:\n";
    std::cout << "  -d, --directory <DIR>  指定要扫描的目录路径\n";
    std::cout << "  -s, --size <SIZE>      忽略小于指定大小的文件 (例如: 100k, 1M)\n";
    std::cout << "                         默认值为 100k\n";
    std::cout << "  -w, --workers <NUM>    指定工作线程数\n";
    std::cout << "                         默认为CPU核心数的1.5倍\n";
    std::cout << "  -c, --check            检查数据库中的文件是否存在\n";
    std::cout << "                         如果文件不存在，则删除该记录\n";
    std::cout << "  -q, --query            查询MD5相同的文件，按文件从大到小排序\n";
    std::cout << "  -h, --help             显示此帮助信息\n\n";
    std::cout << "使用示例:\n";
    std::cout << "  filescanner -d <目录> [-s <文件大小>] [-w <线程数>]  扫描目录文件\n";
    std::cout << "  filescanner -c                                     检查数据库中的文件\n";
    std::cout << "  filescanner -q                                     查询重复文件\n";
}

} // namespace FileScanner
